package com.example.schedule;

import ch.qos.logback.core.util.TimeUtil;
import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@SpringBootApplication
public class ScheduleApplication {
    private final static Logger log = LoggerFactory.getLogger(ScheduleApplication.class);

    public static void main(String[] args) {
        SpringApplication.run(ScheduleApplication.class, args);
//    schedule();
//        scheduleAtFixedRate();
      //  scheduleWithFixedDelay();
    }
    @SneakyThrows
    public static void schedule() {
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
        //延迟一秒执行一个任务
        executorService.schedule(new Runnable() {
            @Override
            @SneakyThrows
            public void run() {
                log.info("run :{}", LocalDateTime.now());
            }
        }, 1000, TimeUnit.MILLISECONDS);
        // waiting to process(sleep to mock)
        Thread.sleep(1000);


        //stop
        executorService.shutdown();
    }

    /**
     * scheduleAtFixedRate最大的特点是保证了总时间段内的执行次数
     *
     */
    @SneakyThrows
    public static void scheduleAtFixedRate() {
        // 多线程保证值不受影响
        AtomicInteger atomicInteger = new AtomicInteger(0);
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
        //延迟一秒执行一个任务
        executorService.scheduleAtFixedRate(new Runnable() {
                                                @Override
                                                @SneakyThrows
                                                public void run() {
                                                    log.info("atomicInteger:{}", atomicInteger.get());
                                                    //获取自增前的值并且自增
                                                    if (atomicInteger.getAndIncrement() == 2) {
                                                        Thread.sleep(7000); // 执行时间超过执行周期
                                                    }
                                                    log.info("run scheduleAtFixedRate @ {}", LocalDateTime.now());
                                                }
                                            }, 500,  //初始化延迟0.5秒执行
                1000, //每隔一秒执行
                TimeUnit.MILLISECONDS);
        // waiting to process(sleep to mock)
        Thread.sleep(10000);

        //stop
        executorService.shutdown();
    }


    /**
     * 每秒执行一次，延迟0.5秒执行。
     */
    @SneakyThrows
    public static void scheduleWithFixedDelay() {
        AtomicInteger count = new AtomicInteger(0);
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
        executor.scheduleWithFixedDelay(
                new Runnable() {
                    @Override
                    @SneakyThrows
                    public void run() {
                        if (count.getAndIncrement()==2) {
                            Thread.sleep(5000); // 执行时间超过执行周期
                        }
                        log.info("run scheduleWithFixedDelay @ {}", LocalDateTime.now());
                    }
                },
                500,
                1000, // 上次执行完成后，延迟多久执行
                TimeUnit.MILLISECONDS);

        // waiting to process(sleep to mock)
        Thread.sleep(10000);

        // stop
        executor.shutdown();
    }

}
